package com.babel.util.ciphers;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

public final class DigestUtils {
	public static final String DEFAULT_ENCODING = "UTF-8";

	public static final Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_ENCODING);

	public static final String KEY_ALGORITHM = "DESede";
	// 算法名称/加密模式/填充方式
    public static final String CIPHER_ALGORITHM_ECB = "DESede/ECB/PKCS5Padding";

	public static String digest(String in) {
		try {
			return DatatypeConverter.printHexBinary(digest(in.getBytes("UTF-8"))).toLowerCase();
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	private static byte[] digest(byte[] in) {
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			messageDigest.reset();
			return messageDigest.digest(in);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * base64 加密
	 *
	 * @param text
	 * @return
	 */
	public static String base64(String text) {
		return base64(text.getBytes(DEFAULT_CHARSET));
	}

	/**
	 * base64 加密
	 *
	 * @param bytes
	 * @return
	 */
	public static String base64(byte[] bytes) {
		return new String(Base64.encodeBase64(bytes), DEFAULT_CHARSET);
	}

	/**
	 * base64 解密
	 *
	 * @param base64Text
	 * @return
	 */
	public static byte[] decodeBase64(String base64Text) {
		return decodeBase64(base64Text.getBytes(DEFAULT_CHARSET));
	}

	/**
	 * base64 解密
	 *
	 * @param base64Bytes
	 * @return
	 */
	public static byte[] decodeBase64(byte[] base64Bytes) {
		return Base64.decodeBase64(base64Bytes);
	}

	public static String base64URLSafe(byte[] bytes) {
		return new String(Base64.encodeBase64URLSafe(bytes), DEFAULT_CHARSET);
	}

	/**
	 * MD5 加密
	 *
	 * @param text
	 * @return
	 */
	public static String md5(String text) {
		return md5(text.getBytes(DEFAULT_CHARSET));
	}

	/**
	 * MD5 加密
	 *
	 * @param bytes
	 * @return
	 */
	public static String md5(byte[] bytes) {
		return org.apache.commons.codec.digest.DigestUtils.md5Hex(bytes);
	}

	/**
	 * HEX 加密
	 *
	 * @param bytes
	 * @return
	 */
	public static String hex(byte[] bytes) {
		return new String(Hex.encodeHex(bytes));
	}

	/**
	 * HEX 解密
	 *
	 * @param text
	 * @return
	 */
	public static byte[] decodeHex(String text) {
		try {
			return Hex.decodeHex(text.toCharArray());
		} catch (DecoderException e) {
			throw new IllegalArgumentException(e);
		}
	}

	public static String sha512(String text) {
		return org.apache.commons.codec.digest.DigestUtils.sha512Hex(text);
	}

	public static byte[] sha512(byte[] text) {
		return org.apache.commons.codec.digest.DigestUtils.sha512(text);
	}

	public static String urlEncode(String url) {
		try {
			return URLEncoder.encode(url, DEFAULT_ENCODING);
		} catch (UnsupportedEncodingException e) {
			return null;
		} catch (Exception e) {
			return null;
		}
	}

	public static String urlDecode(String url) {
		try {
			return URLDecoder.decode(url, DEFAULT_ENCODING);
		} catch (UnsupportedEncodingException e) {
			return null;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * Triple DES 加密
	 *
	 * @param input
	 * @param key
	 * @return
	 */
	public static byte[] tripleEncrypt(String input, String key) {
		byte[] crypted = null;
		try {
			SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "DESede");
			Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB);
			cipher.init(Cipher.ENCRYPT_MODE, skey);
			crypted = cipher.doFinal(input.getBytes(DEFAULT_ENCODING));
		} catch (Exception e) {
			return null;
		}
		return crypted;
	}

	/**
	 * Triple DES 解密
	 *
	 * @param input
	 * @param key
	 * @return
	 */
	public static String tripleDecrypt(byte[] input, String key) {
		byte[] output = null;
		try {
			SecretKeySpec skey = new SecretKeySpec(key.getBytes(DEFAULT_ENCODING), "DESede");
			Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB);
			cipher.init(Cipher.DECRYPT_MODE, skey);
			output = cipher.doFinal(input);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return new String(output);
	}

	private DigestUtils() {
	}

    public static String getRandomGUID(boolean secure){
        String valueBeforeMD5 = "";
        String valueAfterMD5 = "";
        try {
            SecureRandom mySecureRand = new SecureRandom();
            String s_id = InetAddress.getLocalHost().toString();
            MessageDigest md5 = null;
            StringBuffer sbValueBeforeMD5 = new StringBuffer(128);
            md5 = MessageDigest.getInstance("MD5");
            long time = System.currentTimeMillis();
            long rand = 0L;
            if (secure)
                rand = mySecureRand.nextLong();
            else {
                rand = new Random().nextLong();
            }
            sbValueBeforeMD5.append(s_id);
            sbValueBeforeMD5.append(":");
            sbValueBeforeMD5.append(Long.toString(time));
            sbValueBeforeMD5.append(":");
            sbValueBeforeMD5.append(Long.toString(rand));
            valueBeforeMD5 = sbValueBeforeMD5.toString();
//            System.out.println(valueBeforeMD5);
            md5.update(valueBeforeMD5.getBytes());

            byte[] array = md5.digest();
            StringBuffer sb = new StringBuffer(32);
            for (int j = 0; j < array.length; j++) {
                int b = array[j] & 0xFF;
                if (b < 16)
                    sb.append('0');
                sb.append(Integer.toHexString(b));
            }
            valueAfterMD5 = sb.toString();
        } catch (Exception e) {
        }
        return valueAfterMD5;
    }

	public static void main(String[] args) throws IOException, Exception {
//		String data = "{\"username\" : \"zmch999999999\",\"img\" : \"https://static.caihang.com/public/headImg/2016080509373789633.jpeg\",\"mobile\" : \"18210213613\",\"name\" : \"18210213613\",\"labelMap\" : {\"9\" : \"理财达人\"}}";
//		String secretKey = "1GTBJyYo5MRdEA2RXNA0FjoD";
//		byte[] dataByte = DigestUtils.tripleEncrypt(data, secretKey);
//		String dataStr = DigestUtils.base64(dataByte);
//		dataStr = DigestUtils.urlEncode(dataStr);

		System.out.print(DigestUtils.getRandomGUID(false));
	}
}
